﻿/*
// Exepack.NET compressor
// http://www.codeplex.com/exepack
//
// User interface builder
// Written by Y [14-02-09]
// Copyright (c) 2008-2010 Alexey Yakovlev
*/

using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace Exepack
{
	/// <summary>
	/// Declarative UI builder
	/// </summary>
	internal static class UserInterfaceHelper
	{
		/// <summary>
		/// Builds menus and toolbars using provided's methods decorated with ToolButton and MenuItem attributes
		/// </summary>
		/// <param name="provider">Provider (either main form or some plugin)</param>
		/// <param name="toolBar">Tool bar to add buttons to</param>
		/// <param name="mainMenu">Menu to insert commands to</param>
		public static void BuildMenus(this object provider, ToolStrip toolBar, MenuStrip mainMenu)
		{
			foreach (var mi in provider.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic))
			{
				foreach (var button in mi.GetCustomAttributes<ToolButtonAttribute>())
				{
					var handler = mi.CreateDelegate<EventHandler>(provider);
					toolBar.AddButton(button, handler);
				}

				foreach (var mb in mi.GetCustomAttributes<MenuItemAttribute>())
				{
					var handler = mi.CreateDelegate<EventHandler>(provider);
					mainMenu.AddMenuItem(mb, handler);
				}
			}
		}

		static void AddButton(this ToolStrip toolBar, ToolButtonAttribute button, EventHandler handler)
		{
			ToolStripButton b = new ToolStripButton();
			b.Text = button.Name;
			b.Click += handler;
			if (!String.IsNullOrEmpty(button.Image))
				b.Image = LoadImage(button.Image);
			toolBar.Items.Add(b);
		}

		public static void LoadImages(this ImageList imageList, params object[] images)
		{
			foreach (object obj in images)
			{
				if (obj is string)
				{
					imageList.Images.Add(LoadImage(obj.ToString()));
					continue;
				}
				
				if (obj is Enum)
				{
					var icon = obj.GetType().GetField(obj.ToString()).GetCustomAttribute<IconAttribute>();
					imageList.Images.Add(LoadImage(icon.Name));
				}
			}
		}

		static Image LoadImage(string resourceName)
		{
			using (var s = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
			{
				return Image.FromStream(s);
			}
		}

		static void AddMenuItem(this MenuStrip menuStrip, MenuItemAttribute menuItem, EventHandler handler)
		{
			ToolStripItemCollection items = menuStrip.Items;
			ToolStripMenuItem mi = null;

			foreach (string itemText in menuItem.Path)
			{
				mi = items.FindOrCreateMenuItem(itemText);
				items = mi.DropDownItems;
			}

			if (mi != null)
			{
				if (menuItem.Separated)
				{
					ToolStripSeparator separator = new ToolStripSeparator();
					items = (mi.OwnerItem as ToolStripMenuItem).DropDownItems;
					items.Insert(items.IndexOf(mi), separator);
				}

				mi.Text = menuItem.Name;
				mi.Click += handler;
			}
		}

		static ToolStripMenuItem FindOrCreateMenuItem(this ToolStripItemCollection items, string text)
		{
			foreach (ToolStripMenuItem item in items)
			{
				if (item.Text == text)
					return item;
			}

			ToolStripMenuItem menuItem = new ToolStripMenuItem();
			menuItem.Text = text;
			items.Add(menuItem);
			return menuItem;
		}
	}
}
